package search;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Stack;
import mapapp.ConnectToDatabase;


/**
 *
 * @author Haniela
 */
public class Breadth {

    final int MAX = 1000; // maximum number of connections
    // This arraylist holds the route information.
    ArrayList<TraseuInfo> trasee = new ArrayList<TraseuInfo>();
    public Stack btStack = new Stack(); // backtrack stack

    // Get the route database.
    public void setup() {
        ConnectToDatabase connection = new ConnectToDatabase();
        java.sql.PreparedStatement statement = null;
        ResultSet result = null;

        try {
            statement = connection.getConnection().prepareStatement("SELECT * FROM `grafstatii`");
            result = statement.executeQuery();
            while (result.next()) {
                String from = result.getString(2);
                String to = result.getString(3);
                TraseuInfo ti = new TraseuInfo(from, to);
                addTraseu(ti);
            }


        } catch (SQLException e) {
            System.out.println(e.getMessage());
        } finally {
            try {
                if (result != null) {
                    result.close();
                }
                if (statement != null) {
                    statement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                // ignore
            }
        }


    }

    void addTraseu(TraseuInfo ti) {

        trasee.add(ti);
    }

    public ArrayList<String> route(String to) {
        ArrayList<String> statii = new ArrayList<String>();
        String numeStF = null;
        String numeStT = null;
        Stack rev = new Stack();
        double dist = 0;
        TraseuInfo ti;
        int num = btStack.size();
        // Reverse the stack to display route.
        for (int i = 0; i < num; i++) {
            rev.push(btStack.pop());
        }

        System.out.print("De la statia ");
        for (int i = 0; i < num; i++) {
            ti = (TraseuInfo) rev.pop();

            ConnectToDatabase connection = new ConnectToDatabase();
            java.sql.PreparedStatement statement1 = null;
            java.sql.PreparedStatement statement2 = null;
            ResultSet result1 = null;
            ResultSet result2 = null;

            try {
                statement1 = connection.getConnection().prepareStatement("SELECT * FROM `toatestatiile` WHERE `id_statie` LIKE " + ti.IDfrom + "");
                statement2 = connection.getConnection().prepareStatement("SELECT * FROM `toatestatiile` WHERE `id_statie` LIKE " + ti.IDto + "");
                result1 = statement1.executeQuery();
                result2 = statement2.executeQuery();
                while (result1.next()) {
                    numeStF = result1.getString(2);

                }
                while (result2.next()) {
                    numeStT = result2.getString(2);

                }


            } catch (SQLException e) {
                System.out.println(e.getMessage());
            } finally {
                try {
                    if (result1 != null) {
                        result1.close();
                    }
                    if (statement1 != null) {
                        statement1.close();
                    }
                    if (result2 != null) {
                        result2.close();
                    }
                    if (statement2 != null) {
                        statement2.close();
                    }
                    if (connection != null) {
                        connection.close();
                    }
                } catch (SQLException e) {
                    // ignore
                }
            }

            System.out.print(numeStF + " la statia ");
            statii.add(numeStF);
            dist += ti.distance;
        }
        System.out.println(numeStT);
        statii.add(numeStT);
        System.out.printf("Distanta parcursa este %.2f km", dist / 1000);
        System.out.println();

        return statii;
    }

    public double match(String from, String to) {
        for (int i = trasee.size() - 1; i >= 0; i--) {
            if (trasee.get(i).IDfrom.equals(from) && trasee.get(i).IDto.equals(to) && !trasee.get(i).skip) {
                trasee.get(i).skip = true; // prevent reuse
                return trasee.get(i).distance;
            }
        }
        return 0; // not found
    }
    // Given from, find any connection.

    TraseuInfo find(String from) {

        for (int i = 0; i < trasee.size(); i++) {
            if (trasee.get(i).IDfrom.equals(from) && !trasee.get(i).skip) {
                TraseuInfo ti = new TraseuInfo(trasee.get(i).IDfrom, trasee.get(i).IDto);
                trasee.get(i).skip = true; // prevent reuse
                return ti;
            }
        }
        return null;
    }

    // Determine if there is a route between from and to.
    public void isRoute(String from, String to) {
        double dist, dist2;
        TraseuInfo ti;
        Stack resetStck = new Stack();
        // See if at destination.
        dist = match(from, to);
        if (dist != 0) {
            btStack.push(new TraseuInfo(from, to));
            return;
        }

        //Check all connecting routes from a specified node.
        while ((ti = find(from)) != null) {
            resetStck.push(ti);
            if ((dist = match(ti.IDto, to)) != 0) {
                resetStck.push(ti.IDto);
                btStack.push(new TraseuInfo(from, ti.IDto));
                btStack.push(new TraseuInfo(ti.IDto, to));
                return;
            }
        }
        //Reset the skip fields set by preceding while loop.
        int i = resetStck.size();
        for (; i != 0; i--) {
            resetSkip((TraseuInfo) resetStck.pop());
        }

    // Try another connection.
        ti = find(from);
        if (ti != null) {
            btStack.push(new TraseuInfo(from, to));
            isRoute(ti.IDto, to);
        } else if (btStack.size() > 0) {
            // Backtrack and try another connection.
            ti = (TraseuInfo) btStack.pop();
            isRoute(ti.IDfrom, ti.IDto);
        }
    }

    // Reset skip field of specified route.
    void resetSkip(TraseuInfo ti) {
        for (int i = 0; i < trasee.size(); i++) {
            if (trasee.get(i).IDfrom.equals(ti.IDfrom)
                    && trasee.get(i).IDto.equals(ti.IDto)) {
                trasee.get(i).skip = false;
            }
        }
    }
}
